﻿Imports FairShop
Imports FairShop.Objects
Imports FairShop.Presenters
Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Text
Imports System.Text.RegularExpressions

<TestClass()> _
Public Class TestVerkoopDetailsPresenter

    Private testContextInstance As TestContext

    '''<summary>
    '''Gets or sets the test context which provides
    '''information about and functionality for the current test run.
    '''</summary>
    Public Property TestContext() As TestContext
        Get
            Return testContextInstance
        End Get
        Set(ByVal value As TestContext)
            testContextInstance = value
        End Set
    End Property

    Private Class Stap
        Public Operatie As String
        Public Toestemming As Boolean
        Public Nummeringen As String
        Public HuidigNummer As Integer
        Public Statussen As String
    End Class

#Region "Additional test attributes"
    '
    ' You can use the following additional attributes as you write your tests:
    '
    ' Use ClassInitialize to run code before running the first test in the class
    '<ClassInitialize()> _
    'Public Shared Sub MyClassInitialize(ByVal testContext As TestContext)
    'End Sub
    '
    ' Use ClassCleanup to run code after all tests in a class have run
    ' <ClassCleanup()> Public Shared Sub MyClassCleanup()
    ' End Sub
    '
    ' Use TestInitialize to run code before running each test
    ' <TestInitialize()> Public Sub MyTestInitialize()
    ' End Sub
    '
    ' Use TestCleanup to run code after each test has run
    <TestCleanup()> _
    Public Sub MyTestCleanup()
        Utility.ResetData()  ' zodat eventuele overgebleven wijzigingen niet doorgaat naar andere tests
    End Sub

#End Region

    <TestMethod()> _
    Public Sub NummeringTest()
        Dim scenarios As List(Of List(Of Stap)) = ReadScenarios()
        For Each scenario As List(Of Stap) In scenarios
            Dim omschrijving As String = String.Empty

            Utility.Data.VerkoopsDetails.Clear()
            Utility.Data.AcceptChanges()
            Dim presenter As New VerkoopDetailsPresenter(Nothing, Utility.Data.Verkopen(0))

            For Each stap As Stap In scenario
                omschrijving &= stap.Operatie
                VoerOperatieUitEnTest(presenter, omschrijving, stap.Operatie, stap.Toestemming, stap.Nummeringen, stap.HuidigNummer, stap.Statussen)
            Next
        Next
    End Sub

    <TestMethod()> _
    Public Sub VerwijderenGepauzeerdeKlantTest()
        Utility.Data.VerkoopsDetails.Clear()
        Utility.Data.AcceptChanges() ' verwijdert de verkoopsdetails alleen in het geheugen, niet in de databank
        Dim presenter As New VerkoopDetailsPresenter(Nothing, Utility.Data.Verkopen(0))
        Dim artikelDs As ArtikelsDataSet = DirectCast(presenter.Verkoop.Table.DataSet, ArtikelsDataSet)
        Dim verkoopRij As ArtikelsDataSet.VerkopenRow = artikelDs.Verkopen(0)
        Dim artikelRij1 As ArtikelsDataSet.ArtikelsRow = artikelDs.Artikels(0)
        Dim artikelRij2 As ArtikelsDataSet.ArtikelsRow = artikelDs.Artikels(1)
        Dim artikelRij3 As ArtikelsDataSet.ArtikelsRow = artikelDs.Artikels(2)
        Dim aantal1 As Integer = 1
        Dim prijs1 As Decimal = 1.0
        Dim aantal2 As Integer = 2
        Dim prijs2 As Decimal = 2.0
        Dim aantal3 As Integer = 3
        Dim prijs3 As Decimal = 3.0

        ' nieuw artikel voor huidige klant
        presenter.ToevoegenVerkoopsDetail(verkoopRij, artikelRij1, prijs1, "", aantal1)
        Assert.AreEqual(Of Decimal)(prijs1 * aantal1, presenter.TeBetalen)
        Assert.AreEqual(1, presenter.HuidigeKlantVolgnummer)
        ' pauze, zet klant in wacht
        presenter.KlantInOfUitWachtZetten()
        Assert.AreEqual(Of Decimal)(0D, presenter.TeBetalen)
        Assert.AreEqual(2, presenter.HuidigeKlantVolgnummer)
        ' nieuw artikel voor huidige klant
        presenter.ToevoegenVerkoopsDetail(verkoopRij, artikelRij2, prijs2, "", aantal2)
        Assert.AreEqual(Of Decimal)(prijs2 * aantal2, presenter.TeBetalen)
        Assert.AreEqual(2, presenter.HuidigeKlantVolgnummer)
        ' verwijder artikel van klant in wacht
        Dim verkoopsdetail1 As ArtikelsDataSet.VerkoopsDetailsRow = (From vd In verkoopRij.GetVerkoopsDetailsRows() _
                                                                     Where vd.Aantal = aantal1).First
        presenter.VerwijderenVerkoopsDetail(verkoopsdetail1)
        Assert.AreEqual(Of Decimal)(prijs2 * aantal2, presenter.TeBetalen)
        Assert.AreEqual(1, presenter.HuidigeKlantVolgnummer) ' klant in wacht moet nu verdwenen zijn, en zijn volgnummer ook
        ' pauze, zet klant in wacht
        presenter.KlantInOfUitWachtZetten()
        Assert.AreEqual(Of Decimal)(0D, presenter.TeBetalen)
        Assert.AreEqual(2, presenter.HuidigeKlantVolgnummer)
        ' nieuw artikel voor huidige klant
        presenter.ToevoegenVerkoopsDetail(verkoopRij, artikelRij3, prijs3, "", aantal3)
        Assert.AreEqual(Of Decimal)(prijs3 * aantal3, presenter.TeBetalen)
        Assert.AreEqual(2, presenter.HuidigeKlantVolgnummer)
    End Sub

#Region "Helpers"

    Private Function ReadScenarios() As List(Of List(Of Stap))
        Dim scenarios As New List(Of List(Of Stap))

        ' lees de tabel met scenario's en verwachte resultaten
        Dim tabelPath As String = GetScenariosFileNaam()
        Using scenarioReader As New StreamReader(tabelPath)
            Dim line As String = scenarioReader.ReadLine()
            While line.StartsWith("-")
                line = scenarioReader.ReadLine()
            End While
            Dim scenario As New List(Of Stap)
            While line IsNot Nothing
                If (line.Length > 0) Then ' lege lijnen negeren
                    If (Not line.StartsWith("-")) Then ' commentaarlijnen negeren
                        line = Regex.Replace(line, "\s+", ";") ' whitespace vervangen door puntkomma
                        line = line.TrimEnd(";"c)
                        Dim arrContents() As String = line.Split(";"c)
                        ' alle waarden in een stap zetten
                        Dim stap As New Stap
                        stap.Operatie = arrContents(0)
                        stap.Toestemming = (arrContents(1) = "1")
                        stap.Nummeringen = arrContents(2)
                        If (stap.Nummeringen = "-") Then stap.Nummeringen = ""
                        stap.HuidigNummer = Convert.ToInt32(arrContents(3))
                        stap.Statussen = arrContents(4)
                        If (stap.Statussen = "-") Then stap.Statussen = ""
                        scenario.Add(stap)
                    Else ' bij commentaarregel nieuw scenario starten
                        scenarios.Add(scenario)
                        scenario = New List(Of Stap)
                    End If
                End If
                line = scenarioReader.ReadLine()
            End While
        End Using
        Return scenarios
    End Function

    Private Function GetScenariosFileNaam() As String
        Dim diTestDeployFolder As New DirectoryInfo(TestContext.TestDir)
        Dim diSolutionRoot As DirectoryInfo = diTestDeployFolder.Parent.Parent
        Dim diTestFolder As DirectoryInfo = diSolutionRoot.GetDirectories("FairShopTesting")(0)
        Dim diTestDataFolder As DirectoryInfo = diTestFolder.GetDirectories("TestData")(0)
        Dim testScenariosFileNaam As String = Path.Combine(diTestDataFolder.FullName, "nummering-scenarios.txt")
        Return testScenariosFileNaam
    End Function

    Private Sub VoerOperatieUitEnTest(ByVal presenter As VerkoopDetailsPresenter, _
            ByVal scenario As String, ByVal operatie As String, ByVal verwachteToestemming As Boolean, _
            ByVal verwachteNummering As String, ByVal verwachteHuidigeNummer As Integer, ByVal verwachteStatus As String)
        Console.WriteLine("Test voor scenario " & scenario) ' verschijnt in test run results
        Select Case operatie
            Case "N" ' nieuw artikel voor huidige klant
                Dim artikelDs As ArtikelsDataSet = DirectCast(presenter.Verkoop.Table.DataSet, ArtikelsDataSet)
                Dim verkoopRij As ArtikelsDataSet.VerkopenRow = artikelDs.Verkopen(0)
                Dim artikelRij As ArtikelsDataSet.ArtikelsRow = artikelDs.Artikels(0)
                presenter.ToevoegenVerkoopsDetail(verkoopRij, artikelRij, 2.5, "", 1)
            Case "P" ' pauze, zet klant in of uit wacht
                Assert.AreEqual(verwachteToestemming, presenter.KanInOfUitWachtZetten, "Toestemming om te pauzeren klopt niet bij scenario " & scenario)
                presenter.KlantInOfUitWachtZetten()
            Case "O" ' ongedaan, maak de huidige klant ongedaan
                Assert.AreEqual(verwachteToestemming, presenter.KanKlantOngedaanMaken, "Toestemming om ongedaan te maken klopt niet bij scenario " & scenario)
                presenter.KlantOngedaanMaken()
            Case "A" ' afrekenen, reken de huidige klant af
                Assert.AreEqual(verwachteToestemming, presenter.KanAfrekenen, "Toestemming om af te rekenen klopt niet bij scenario " & scenario)
                presenter.KlantAfrekenen()
            Case Else
                Throw New Exception("Operatie niet geïmplementeerd")
        End Select

        Dim actueleHuidigeNummer As Integer = presenter.HuidigeKlantVolgnummer
        Assert.AreEqual(verwachteHuidigeNummer, actueleHuidigeNummer, "Huidige nummer klopt niet bij scenario " & scenario)

        Dim actueleNummering As String = ""
        Dim actueleStatus As String = ""
        For Each row As ArtikelsDataSet.VerkoopsDetailsRow In presenter.Verkoop.GetVerkoopsDetailsRows
            If (Not actueleNummering = "") Then actueleNummering &= ","
            actueleNummering &= row.VolgnummerKlant.ToString()
            If (actueleStatus.Length > 0) Then actueleStatus &= ","
            Select Case row.Status
                Case StatusImage.Huidig
                    actueleStatus &= "H"
                Case StatusImage.InWacht
                    actueleStatus &= "P"
                Case StatusImage.Afgerekend
                    actueleStatus &= "A"
            End Select
        Next
        Assert.AreEqual(verwachteNummering, actueleNummering, "Nummering klopt niet bij scenario " & scenario)
        Assert.AreEqual(verwachteStatus, actueleStatus, "Status klopt niet bij scenario " & scenario)
    End Sub

#End Region

End Class
